# -*- coding: UTF-8 -*-
'''
Created on 05.02.2013

@author: p.hess
'''

import numpy as np
import math

class Transform(object):
    '''
    transform incomming spread. 
    '''

    def __init__(self, 
                 Transform_in=None,
                 TranslateX_in=([0.0]), 
                 TranslateY_in=([0.0]), 
                 ScaleX_in=([1.0]), 
                 ScaleY_in=([1.0]),
                 Rotate_in=([0.0]) 
                 ):
        '''
        Constructor
        translateX_in - np.array of float 
        translateY_in - np.array of float
        scaleX_in - np.array of float
        scaleY_in - np.array of float
        
        '''
        self.transform_in = Transform_in
        self.translateX_in = TranslateX_in
        self.translateY_in = TranslateY_in
        self.scaleX_in = ScaleX_in
        self.scaleY_in = ScaleY_in
        self.rotate_in = Rotate_in
        self.dirty = True
        self.roti = 0
        
    def update(self, Transform_in=None, TranslateX_in=None, TranslateY_in=None, ScaleX_in=None, ScaleY_in=None, Rotate_in=None):

        if (Transform_in != None and not np.array_equal(self.transform_in, Transform_in)): 
            self.transform_in = Transform_in 
            self.dirty = True
        if (TranslateX_in != None and not np.array_equal(self.translateX_in, TranslateX_in)): 
            self.translateX_in = TranslateX_in 
            self.dirty = True
        if (TranslateY_in != None and not np.array_equal(self.translateY_in, TranslateY_in)): 
            self.translateY_in = TranslateY_in
            self.dirty = True
        if (ScaleX_in != None and not np.array_equal(self.scaleX_in, ScaleX_in)): 
            self.scaleX_in = ScaleX_in
            self.dirty = True
        if (ScaleY_in != None and not np.array_equal(self.scaleY_in, ScaleY_in)): 
            self.scaleY_in = ScaleY_in
            self.dirty = True
        if (Rotate_in != None and not np.array_equal(self.rotate_in, Rotate_in)): 
            self.rotate_in = Rotate_in
            self.dirty = True            
            
        if not self.dirty:
            return

        self.dirty = False;
                
        if (self.transform_in == None): lt = 0
        else: lt = 1 #len(self.transform_in)
        p = np.array([lt,
                      len(self.translateX_in), 
                      len(self.translateY_in), 
                      len(self.scaleX_in), 
                      len(self.scaleY_in), 
                      len(self.rotate_in)]
                     )
        self.maxcount = p.max() 
        r = range(self.maxcount)
        
        # prepare the targets
       
        self.translateX = np.arange(self.maxcount, dtype=np.float)
        self.translateY = np.arange(self.maxcount, dtype=np.float)
        self.scaleX = np.arange(self.maxcount, dtype=np.float)
        self.scaleY = np.arange(self.maxcount, dtype=np.float)
        self.rotate = np.arange(self.maxcount, dtype=np.float)
        
        # fill the internal spreads. If a output is too short for maxcount
        # it's internal data is wrapped and replicated until the output
        # has the lenght of maxcount
        self.transform = self.transform_in
        np.put(self.translateX, r, self.translateX_in)
        np.put(self.translateY, r, self.translateY_in)
        np.put(self.scaleX, r, self.scaleX_in)
        np.put(self.scaleY, r, self.scaleY_in)
        np.put(self.rotate, r, self.rotate_in)
        # do the transformation 
    
        # build the transform hash as return value        
        self.transform_out = CargoTransform(
                                         self.maxcount,
                                         self.transform,
                                         self.translateX,
                                         self.translateY,
                                         self.scaleX,
                                         self.scaleY,
                                         self.rotate)
        
class CargoTransform:
    
    transformCount = 0;  # static variable to have a unique identifier of CargoTransform objects
    
    def __init__(self, 
                 maxcount=1,
                 transform = None,  
                 translateX=([0.0]), 
                 translateY=([0.0]), 
                 scaleX=([1.0]), 
                 scaleY=([1.0]),
                 rotate=([0.0])
                 ):
        CargoTransform.transformCount += 1
        self.id = CargoTransform.transformCount
        self.maxcount = maxcount
        self.translateX = np.array(translateX)
        self.translateY = np.array(translateY)
        self.scaleX = np.array(scaleX)
        self.scaleY = np.array(scaleY)
        self.rotate = np.array(rotate)

        ### make iteration over all transformation objects ###
        if ( transform != None ):
            ct = transform
            counter=0
            for i in range(self.maxcount):
                
                ### rotate ###
                
                # iterate with ict over the internal structs of the transform object
                ict = counter % ct.maxcount
                rot = ct.rotate[ict]
                counter +=1
                
                rotInRadians = math.radians( rot * 360.0)
                orgx = self.translateX[i]
                orgy = self.translateY[i]
                cos = np.cos(rotInRadians)
                sin = np.sin(rotInRadians)
                self.translateX[i] = (orgx * cos) + (orgy * sin)  
                self.translateY[i] = (orgx * sin * -1.0) + (orgy * cos )
                
                ### position ###
                 
                self.translateX[i] += ct.translateX[ict]
                self.translateY[i] += ct.translateY[ict]
                
                #scale von scale? unklar was das macht, fehlt aber noch
